
#include "string.h"
#include "../lib/byte_bit.h"

#define IDLE_LEVLE		1
#define PULSE_LEVLE		!IDLE_LEVLE


#define SEND_BIT_0			0
#define SEND_BIT_1			1
#define SEND_BIT_SYNC		2
#define SEND_BIT_END		3
#define SEND_BIT_ERROR		4

#define IR_TICK_TIME_IN_US			40UL						

#define SYNC_PULSE_TIME_TICK		6000/IR_TICK_TIME_IN_US
#define SYNC_IDLE_TIME_TICK			7320/IR_TICK_TIME_IN_US

#define BIT0_PULSE_TIME_TICK		530/IR_TICK_TIME_IN_US
#define BIT0_IDLE_TIME_TICK			(2000-530)/IR_TICK_TIME_IN_US

#define BIT1_PULSE_TIME_TICK		530/IR_TICK_TIME_IN_US
#define BIT1_IDLE_TIME_TICK			(4000-530)/IR_TICK_TIME_IN_US

#define END_PULSE_TIME_TICK			530/IR_TICK_TIME_IN_US
#define END_IDLE_TIME_TICK			(8000-530)/IR_TICK_TIME_IN_US

/*
#define SYNC_PULSE_TIME_TICK		9000/IR_TICK_TIME_IN_US		//9000us,
#define SYNC_IDLE_TIME_TICK			4500/IR_TICK_TIME_IN_US

#define BIT0_PULSE_TIME_TICK		560/IR_TICK_TIME_IN_US
#define BIT0_IDLE_TIME_TICK			560/IR_TICK_TIME_IN_US

#define BIT1_PULSE_TIME_TICK		560/IR_TICK_TIME_IN_US
#define BIT1_IDLE_TIME_TICK			1690/IR_TICK_TIME_IN_US

#define END_PULSE_TIME_TICK			560/IR_TICK_TIME_IN_US
#define END_IDLE_TIME_TICK			10000/IR_TICK_TIME_IN_US	//40ms
*/

#define SEND_STATE_SYNC		0
#define SEND_STATE_DATA		1
#define SEND_STATE_END		2
#define SEND_STATE_STOP		3

static void (*bsp_ir_send_hal_set_level_pulse_callback)(void) = 0;
static void (*bsp_ir_send_hal_set_level_idle_callback)(void) = 0;

static uint8_t send_buff[16] = {0};
static uint8_t send_buff_len = 0;
static uint8_t send_byte_i = 0;			//send_bit_count
static uint8_t send_buff_p = 0;			//send_byte_count
static uint8_t send_byte = 0;
static uint8_t send_state = SEND_STATE_STOP;

uint8_t bsp_ir_send_finish_send_falg = 0;
uint8_t bsp_ir_send_busy_falg = 0;

uint8_t bsp_ir_send(uint8_t* send_data, uint8_t send_data_len)
{
	if((bsp_ir_send_busy_falg == 0)&&(send_data_len <= 16)){
		memcpy(send_buff, send_data, send_data_len);
		send_buff_len = send_data_len;
		send_byte_i = 0;			//send_bit_count
		send_buff_p = 0;			//send_byte_count
		bsp_ir_send_busy_falg = 1;
		send_byte = 0;
		send_state = SEND_STATE_SYNC;
		return 1;
	}
	else{
		return 0;
	}
}

#define delay_lable_0_DEF		0
#define delay_lable_1_DEF		1
#define delay_lable_2_DEF		2
#define delay_lable_3_DEF		3
#define delay_lable_4_DEF		4
#define delay_lable_5_DEF		5
#define delay_lable_6_DEF		6
#define delay_lable_7_DEF		7
#define delay_lable_8_DEF		8
#define delay_lable_NONE_DEF	0xff

static uint16_t delay_counter = 0;
static uint8_t delay_lable_id = delay_lable_NONE_DEF;

void bsp_ir_send_tick_handler(void)
{
	if(bsp_ir_send_busy_falg == 0){
		return;
	}

	if(delay_counter > 0){
		delay_counter--;
	}
	if(delay_counter > 0){
		return;
	}
	else{
        switch(delay_lable_id){
			case delay_lable_0_DEF:
				goto delay_lable_0;
				break;

			case delay_lable_1_DEF:
				goto delay_lable_1;
				break;

//			case delay_lable_2_DEF:
//				goto delay_lable_2;
//				break;

			case delay_lable_3_DEF:
				goto delay_lable_3;
				break;
			
			case delay_lable_4_DEF:
				goto delay_lable_4;
				break;

			case delay_lable_5_DEF:
				goto delay_lable_5;
				break;
			
			case delay_lable_6_DEF:
				goto delay_lable_6;
				break;

			case delay_lable_7_DEF:
				goto delay_lable_7;
				break;
			
			case delay_lable_8_DEF:
				goto delay_lable_8;
				break;
			
			case delay_lable_NONE_DEF:
				goto delay_lable_none;
			default:
				break;
        }
	}
	
delay_lable_none:	
    if(send_state == SEND_STATE_SYNC){
        bsp_ir_send_hal_set_level_pulse_callback();
/*******************************/
        delay_counter = SYNC_PULSE_TIME_TICK;
        delay_lable_id = delay_lable_0_DEF;
        return;
delay_lable_0:
/*******************************/
        bsp_ir_send_hal_set_level_idle_callback();
/*******************************/		
        delay_counter = SYNC_IDLE_TIME_TICK;
        delay_lable_id = delay_lable_1_DEF;
        return;
delay_lable_1:
/*******************************/
		send_state = SEND_STATE_DATA;
/*******************************/
		delay_lable_id = delay_lable_NONE_DEF;
/*******************************/
    }
    else if(send_state == SEND_STATE_DATA){
        if(send_byte_i == 0){
            send_byte = send_buff[send_buff_p];
            send_buff_p++;
        }
        if ((send_byte & 0x01) == 0){
        	bsp_ir_send_hal_set_level_pulse_callback();
/*******************************/
			delay_counter = BIT0_PULSE_TIME_TICK;
			delay_lable_id = delay_lable_3_DEF;
			return;
delay_lable_3:
/*******************************/
       		bsp_ir_send_hal_set_level_idle_callback();
/*******************************/
			delay_counter = BIT0_IDLE_TIME_TICK;
			delay_lable_id = delay_lable_4_DEF;
			return;
delay_lable_4:
/*******************************/
/*******************************/
			delay_lable_id = delay_lable_NONE_DEF;
/*******************************/
        }
        else{
        	bsp_ir_send_hal_set_level_pulse_callback();
/*******************************/
			delay_counter = BIT1_PULSE_TIME_TICK;
			delay_lable_id = delay_lable_5_DEF;
			return;
delay_lable_5:
/*******************************/
       		bsp_ir_send_hal_set_level_idle_callback();
/*******************************/
			delay_counter = BIT1_IDLE_TIME_TICK;
			delay_lable_id = delay_lable_6_DEF;
			return;
delay_lable_6:
/*******************************/
/*******************************/
			delay_lable_id = delay_lable_NONE_DEF;
/*******************************/
        }
        send_byte >>= 1;
        send_byte_i++;

        if(send_byte_i >= 8){
            if(send_buff_p >= send_buff_len){
                send_buff_p = 0;
                send_state = SEND_STATE_END;
            }
            else{
                send_byte_i = 0;
            }
        }
    }

    else if(send_state == SEND_STATE_END){
        bsp_ir_send_hal_set_level_pulse_callback();
/*******************************/
        delay_counter = END_PULSE_TIME_TICK;
        delay_lable_id = delay_lable_7_DEF;
        return;
delay_lable_7:
/*******************************/
        bsp_ir_send_hal_set_level_idle_callback();
/*******************************/		
        delay_counter = END_IDLE_TIME_TICK;
        delay_lable_id = delay_lable_8_DEF;
        return;
delay_lable_8:
/*******************************/
		send_state = SEND_STATE_STOP;
/*******************************/
		delay_lable_id = delay_lable_NONE_DEF;
/*******************************/
    }

	else if(send_state == SEND_STATE_STOP){
		bsp_ir_send_busy_falg = 0;
		bsp_ir_send_finish_send_falg = 1;
	}

	else{
		send_buff_len = 0;
		send_byte_i = 0;			//send_bit_count
		send_buff_p = 0;			//send_byte_count
		bsp_ir_send_busy_falg = 0;
    }
}

void bsp_ir_send_init(void (*bsp_ir_send_hal_init_callbakc_handler)(void),
						void (*bsp_ir_send_hal_set_level_pulse_callback_handler)(void),
						void (*bsp_ir_send_hal_set_level_idle_callback_handler)(void))
{
	if(bsp_ir_send_hal_init_callbakc_handler != 0){
		bsp_ir_send_hal_init_callbakc_handler();
	}
	
	bsp_ir_send_hal_set_level_pulse_callback = bsp_ir_send_hal_set_level_pulse_callback_handler;
	bsp_ir_send_hal_set_level_idle_callback = bsp_ir_send_hal_set_level_idle_callback_handler;
	
	send_buff_len = 0;
	send_byte_i = 0;			//send_bit_count
	send_buff_p = 0;			//send_byte_count
	bsp_ir_send_busy_falg = 0;
	bsp_ir_send_finish_send_falg = 0;
}

void bsp_ir_send_hal_set_level_pulse_callback_register(void (*bsp_ir_send_hal_set_level_pulse_callback_handler)(void))
{
	bsp_ir_send_hal_set_level_pulse_callback = bsp_ir_send_hal_set_level_pulse_callback_handler;
}
     
void bsp_ir_send_hal_set_level_idle_callback_register(void (*bsp_ir_send_hal_set_level_idle_callback_handler)(void))
{
	bsp_ir_send_hal_set_level_idle_callback = bsp_ir_send_hal_set_level_idle_callback_handler;
}